package com.luxf.base.domainevent;

import com.luxf.base.domainevent.model.DomainEventNotice;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;

import javax.annotation.Resource;

public abstract class AbstractDomainEventPublisher implements DomainEventPublisher {

    @Resource
    protected EventNoticeManager eventNoticeManager;

    /**
     * 监听发送DomainEventNotice的事件、(由{@link ApplicationEventPublisher#publishEvent(Object)}发出的事件.)
     * <p>
     * param eventNotice 通知
     */
    @Override
    @TransactionalEventListener
    @Transactional(rollbackFor = Exception.class)
    public void publish(DomainEventNotice eventNotice) {
        if (eventNotice != null) {
            eventNoticeManager.findUnsentNotice(eventNotice).ifPresent(this::doPublish);
            return;
        }
        sendAll();
    }

    @Scheduled(fixedDelayString = "${domain-event.publisher.retry-interval:60000}",
            initialDelayString = "${domain-event.publisher.init-delay:30000}")
    @Transactional
    public void retryPublic() {
        sendAll();
    }

    private void sendAll() {
        // 触发并不直接发送, 而是从数据库进行查询需要发送的消息, 进行发送
        eventNoticeManager.findUnsentNotices().forEach(this::doPublish);
    }

    protected abstract void doPublish(DomainEventNotice notice);

}
